//服务器框架
const express = require("express");
//MongoDB数据库连接工具
const mongoose = require("mongoose");
// 验证码工具
const svgCaptcha = require("svg-captcha")
//请求头cookie解析工具
const cookieParser = require("cookie-parser")
const {errorWrapper} = require("./utils/errorWrapper");
//表结构
const ValidateCode = require("./models/models/ValidateCode")
const Admin = require("./models/models/Admini")
const Contest = require("./models/models/Contest")
const RequestNum = require("./models/models/RequestNum")
const moment = require("moment")
const {success} = require("./utils/success")
const School = require("./models/models/School")
const major = require("./utils/major")


const AESKEY = "hello"

//路由
const userRouter = require("./router/UserRouter")
const adminRouter = require("./router/AdminRouter")


const NodeRSA = require("node-rsa");
const Key = require("./models/models/Key");
const cryptoJS = require("crypto-js");


const port = 80
const app = express();

//验证码失效时间
const vcodeTime = 3 * 60 * 1000

// 跨域请求
app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    // Access-Control-Allow-Headers ,可根据浏览器的F12查看,把对应的粘贴在这里就行
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Methods', '*');
    // res.header('Content-Type', 'application/json;charset=utf-8');
    next();
})

// 请求头 content-type为application/json的参数解析中间件
app.use(express.json())
// 请求头 content-type为 application/x-www-form-urlencoded 表单格式参数解析中间件
app.use(express.urlencoded({extended: true}))
app.use(cookieParser())
app.use("/user", userRouter)
app.use("/Admin", adminRouter)
app.use(express.static('public'))

//返回图片
app.get('/public/img/*', function (req, res) {
    res.sendFile(__dirname + "/" + decodeURI(req.url));
    console.log("Request for " + decodeURI(req.url) + " received.");
})

// 获取验证码
app.get("/validate", errorWrapper(async (req, res) => {
    const captcha = svgCaptcha.create({
        noise: 4,//干扰线
        background: '#cc9966',
        fontSize: 32,
        width: 63.34,
        height: 36.8
    })
    // 保存验证码到数据库中
    const r = await new ValidateCode({code: captcha.text}).save();
    // 过期自动删除验证码
    setTimeout(async () => {
        ValidateCode.findByIdAndDelete(r._id.toString()).then(r => {
            console.log("验证码已过期")
        })
    }, vcodeTime)
    await res.json(success({code: captcha.data, id: r._id}))
}))
// 比对验证码
app.post("/Compare", errorWrapper(async (req, res) => {
    const {valiadate, id} = req.body
    const v = await ValidateCode.findById(id)
    res.json(success({result: valiadate.toLowerCase() === v.code.toLowerCase()}))
}))
app.get("/", (req, res) => {
    console.log("被请求了")
    res.json({data: "成功", code: "200"})
})

// 服务器监听
app.listen(port, '0.0.0.0', () => {
    console.log("run:http://127.0.0.1:" + port)
    mongoose.connect("mongodb://localhost:27017/admin").then(errorWrapper(async () => {
        //初始化学校数据

        //初始化一个管理员账户
        const count = await Admin.count()
        if (await RequestNum.count() === 0) {
            await new RequestNum({num: 0}).save()
        }
        if (count === 0) {
            let pwd = "12345678"
            const account = "SuperAdmin"
            const key = await CreateKey(Key)
            const role = ["SuperAdmin", "Admin"]
            pwd = cryptoJS.AES.encrypt(pwd, AESKEY).toString()
            const admin = await Admin.findOneAndUpdate({account: account},
                {
                    account: account,
                    pwd: pwd,
                    role: role,
                    name: '曹忠孝',
                    schoolName: '1000',
                    collegeName: '10001',
                    technical: '网站维护工程师',
                    roles: ["SuperAdmin", "Admin"]
                }, {upsert: true, new: true})
            key.userID = admin._id
            key.updateTime = new Date()
            key.save()
        }
        if (await School.count() === 0) {
            await School.insertMany(major)
        }
    }))
    const db = mongoose.connection
    db.on('error', err => {
        console.error(err)
    })
    db.once('open', () => {
        console.log('open')
    })
})

// 添加统一异常处理
app.use((err, req, res, next) => {
    if (err) {
        console.error(err)
        res.json({status: "500", msg: err.toString()})
    }
})

// 创建密钥
async function CreateKey(Key) {
    const key = new NodeRSA({b: 512})
    key.generateKeyPair(2048, 65537)
    // 导出密钥
    const publicKey = key.exportKey("pkcs1-public")
    const privateKey = key.exportKey("pkcs1-private")
    // 存入数据库
    const r = await new Key({publicKey, privateKey, userID: ''}).save()
    return r
}